#include "typedef.h"
#include "astraldef.h"
#include "astralapi.h"
#include "task.h"
/*****************************************************************************/
/**                                spin API                                 **/
/*****************************************************************************/
#define SPIN_MAGIC (0b1011 << 4)

boolean spin_lock(AstralSpin lock)
{
    word irq_status = arch_disable_local_irq();

    int coreid = arch_get_cpuid();
    int core_flag = SPIN_MAGIC | coreid;

    while (1)
    {
        if (arch_compare_and_swap(lock, 0x0, core_flag))
        {
            break;
        }

    }

    disable_preempt(coreid);
    arch_enable_local_irq(irq_status);
    return True;
}

boolean spin_unlock(AstralSpin lock)
{
    FORBIT_LOCAL_INT(irqstatus);
    int coreid = arch_get_cpuid();
    int core_flag = SPIN_MAGIC | coreid;
    if(lock->lock != core_flag)
    {
        // bug()
        while(1){}
    }
    lock->lock = 0;
    restore_preempt(coreid);
    RESUME_LOCAL_INT(irqstatus);
    return True;
}

word spin_lock_irq(AstralSpin lock)
{
   FORBIT_LOCAL_INT(irqstatus);
    // ensure that context switch will not occur here
    int coreid = arch_get_cpuid();
    int core_flag = SPIN_MAGIC | coreid;

    if(core_flag == lock->lock)
    {
        //kprint("\033[5m\033[41;97mself deadlocked %d\033[0m\n",coreid);
        while(1)
        {
        }
    }

    while (1)
    {
        boolean got = arch_compare_and_swap(lock, 0x0, core_flag);
        if (got)
        {
            break;
        }
    }
    disable_preempt(coreid);
    return irqstatus;
}

boolean spin_unlock_irq(AstralSpin lock, word irq_status)
{
    int coreid = arch_get_cpuid();
    int core_flag = SPIN_MAGIC | coreid;
    if(lock->lock != core_flag)
    {
        // return False;
        while(1){}
    }
    lock->lock = 0;
    restore_preempt(coreid);
    RESUME_LOCAL_INT(irq_status);
    return True;
}